package com.sy.live.dao.impl;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;

import com.sy.live.dao.IBaseDao;

@SuppressWarnings("unchecked")
@Repository("baseDao")
public class BaseDaoImpl implements IBaseDao
{
	private static final Logger logger = Logger.getLogger(BaseDaoImpl.class);

	@Resource(name = "hibernateTemplate")
	HibernateTemplate hibernateTemplate;

	public <T> boolean addEntity(T t)
	{
		boolean flag = false;
		try
		{
			// 将Entity添加到数据中
			this.hibernateTemplate.persist(t);
			flag = true;
			logger.info("Add Entity[" + t + "] success.");
		} catch (RuntimeException e)
		{
			logger.error("Add Entity[" + t + "] fail. Message:" + e.getMessage(), e);
			throw e;
		}
		return flag;
	}

	public <T> Serializable saveEntity(T t)
	{
		Serializable pk = null;
		try
		{
			pk = this.hibernateTemplate.save(t);
			logger.info("Add Entity[" + t + "] success.");
		} catch (RuntimeException e)
		{
			logger.error("Add Entity[" + t + "] fail. Message:" + e.getMessage(), e);
			throw e;
		}
		return pk;
	}

	public <T> boolean updateEntity(T t)
	{
		boolean flag = false;
		try
		{
			this.hibernateTemplate.update(t);
			flag = true;
			logger.info("Update Entity[" + t + "] success.");
		} catch (RuntimeException e)
		{
			logger.error("Update Entity[" + t + "] fail. Message:" + e.getMessage(), e);
			throw e;
		}
		return flag;
	}

	public <T> boolean deleteEntity(T t)
	{
		boolean flag = false;
		try
		{
			this.hibernateTemplate.delete(t);
			flag = true;
			logger.info("Delete Entity[" + t + "] success.");
		} catch (RuntimeException e)
		{
			logger.error("Delete Entity[" + t + "] fail. Message:" + e.getMessage(), e);
			throw e;
		}
		return flag;
	}

	public <T> T findEntityByPK(Class<T> cla, Serializable pk)
	{
		T t = null;
		try
		{
			t = (T) hibernateTemplate.get(cla, pk);
			logger.info("find Entity[" + t + "] success.");
		} catch (RuntimeException e)
		{
			logger.error("find Entity[" + t + "] fail. Message:" + e.getMessage(), e);
			throw e;
		}
		return t;
	}

	public <T> List<T> findAllEntity(Class<T> cla)
	{
		List<T> list = null;
		list = this.hibernateTemplate.find("from " + cla.getName());
		return list;
	}

	public <T> List<T> findEntityByHql(String hql, Object... params)
	{
		List<T> list = null;
		list = this.hibernateTemplate.find(hql, params);
		return list;
	}

	public boolean executeUpdateSQL(final String sql, final Map<String, Object> params)
	{
		boolean flag = false;
		int row = (int) this.hibernateTemplate.execute(new HibernateCallback<Object>()
		{

			@Override
			public Integer doInHibernate(org.hibernate.Session session) throws HibernateException, SQLException
			{
				SQLQuery query = session.createSQLQuery(sql);
				if (params != null)
				{
					for (String key : params.keySet())
					{
						query.setParameter(key, params.get(key));
					}
				}
				int row = query.executeUpdate();
				return row;
			}

		});
		if (row > 0)
			flag = true;
		return flag;
	}

	public <T> List<T> executeListSQL(final String sql, final Map<String, Object> params)
	{
		return (List<T>) this.hibernateTemplate.execute(new HibernateCallback<Object>()
		{
			public List<T> doInHibernate(Session session) throws HibernateException
			{
				SQLQuery query = session.createSQLQuery(sql);
				if (params != null && params.size() > 0)
				{
					for (String key : params.keySet())
					{
						query.setParameter(key, params.get(key));
					}
				}
				return query.list();
			}
		});
	}

	@SuppressWarnings("rawtypes")
	public boolean executeUpdateHQL(final String hql, final Map params)
	{
		boolean flag = false;
		int row = (int) this.hibernateTemplate.execute(new HibernateCallback()
		{
			public Integer doInHibernate(Session session) throws HibernateException
			{
				Query query = session.createQuery(hql);
				if (params != null)
				{
					for (String key : ((Map<String, Object>) params).keySet())
					{
						query.setParameter(key, params.get(key));
					}
				}
				int row = query.executeUpdate();
				return row;
			}
		});

		if (row > 0)
			flag = true;
		return flag;
	}

	public <T> List<T> executeListHQL(final String hql, final Map<String, Object> params)
	{
		return (List<T>) this.hibernateTemplate.execute(new HibernateCallback<Object>()
		{
			public List<T> doInHibernate(Session session) throws HibernateException
			{
				Query query = session.createQuery(hql);
				if (params != null && params.size() > 0)
				{
					for (String key : ((Map<String, Object>) params).keySet())
					{
						query.setParameter(key, params.get(key));
					}
				}
				return query.list();
			}
		});
	}

	public <T> T executeUniqueHQL(final String hql, final Map<String, Object> params)
	{
		return (T) this.hibernateTemplate.execute(new HibernateCallback<Object>()
		{
			public Object doInHibernate(Session session) throws HibernateException, SQLException
			{
				Query query = session.createQuery(hql);
				if (params != null && params.size() > 0)
				{
					for (String key : ((Map<String, Object>) params).keySet())
					{
						query.setParameter(key, params.get(key));
					}
				}
				query.setMaxResults(1);
				return query.uniqueResult();
			}

		});
	}

	public <T> T executeHQLLimit(final String hql, final Map<String, Object> params, final int firstNum, final int maxNum)
	{
		return (T) this.hibernateTemplate.execute(new HibernateCallback<Object>()
		{
			public Object doInHibernate(Session session) throws HibernateException, SQLException
			{
				Query query = session.createQuery(hql);
				if (params != null && params.size() > 0)
				{
					for (String key : ((Map<String, Object>) params).keySet())
					{
						query.setParameter(key, params.get(key));
					}
				}
				query.setFirstResult(firstNum);
				query.setMaxResults(maxNum);
				return query.list();
			}

		});
	}

	public <T> T executeUniqueHQL(final Class<T> cla)
	{
		return (T) this.hibernateTemplate.execute(new HibernateCallback<Object>()
		{
			public Object doInHibernate(Session session) throws HibernateException, SQLException
			{
				String hql = "from " + cla.getName();
				Query query = session.createQuery(hql);
				query.setMaxResults(1);
				return query.uniqueResult();
			}
		});
	}

	public <T> List<T> getListForPage(final Class<T> arg, final Criterion[] criterions, final int offset, final int length)
	{
		return this.hibernateTemplate.executeFind(new HibernateCallback<Object>()
		{
			public List<T> doInHibernate(Session session) throws HibernateException, SQLException
			{
				Criteria criteria = session.createCriteria(arg);
				// 循环遍历添加约束条件
				for (int i = 0; i < criterions.length; i++)
				{
					if (criterions[i] != null)
					{
						criteria.add(criterions[i]);
					}
				}
				criteria.setFirstResult(offset);
				criteria.setMaxResults(length);
				return criteria.list();
			}
		});

	}

	public <T> List<T> findByCriteria(final DetachedCriteria detachedCriteria)
	{
		return this.hibernateTemplate.executeFind(new HibernateCallback<Object>()
		{
			@Override
			public List<T> doInHibernate(Session session) throws HibernateException, SQLException
			{
				Criteria criteria = detachedCriteria.getExecutableCriteria(session);
				return criteria.list();
			}
		});
	}

	public <T> List<T> findByCriteria(final DetachedCriteria detachedCriteria, final int first, final int max)
	{
		return this.hibernateTemplate.executeFind(new HibernateCallback<Object>()
		{
			public List<T> doInHibernate(Session session) throws HibernateException, SQLException
			{
				Criteria criteria = detachedCriteria.getExecutableCriteria(session);
				criteria.setFirstResult(first).setMaxResults(max);
				return criteria.list();
			}
		});
	}

	public <T> T executeCountListHQL(final String hql, final Map<String, Object> params)
	{
		return (T) this.hibernateTemplate.execute(new HibernateCallback<Object>()
		{
			public Object doInHibernate(Session session) throws HibernateException
			{
				Query query = session.createQuery(hql);
				if (params != null && params.size() > 0)
				{
					for (String key : params.keySet())
					{
						query.setParameter(key, params.get(key));
					}
				}
				return query.uniqueResult();
			}
		});
	}

	public <T> T executeCountByCriterion(final Class<T> arg, final Criterion[] criterions)
	{
		return (T) this.hibernateTemplate.execute(new HibernateCallback<Object>()
		{
			public Object doInHibernate(Session session) throws HibernateException, SQLException
			{
				Criteria criteria = session.createCriteria(arg);
				// 循环遍历添加约束条件
				for (int i = 0; i < criterions.length; i++)
				{
					if (criterions[i] != null)
					{
						criteria.add(criterions[i]);
					}
				}
				criteria.setProjection(Projections.rowCount());
				return criteria.uniqueResult();
			}
		});
	}

	public <T> List<T> executeByCriterion(final Class<T> cla, final Criterion[] criterions)
	{
		return (List<T>) this.hibernateTemplate.execute(new HibernateCallback<Object>()
		{
			public List<T> doInHibernate(Session session) throws HibernateException, SQLException
			{
				Criteria criteria = session.createCriteria(cla);
				// 循环遍历添加约束条件
				for (int i = 0; i < criterions.length; i++)
				{
					if (criterions[i] != null)
					{
						criteria.add(criterions[i]);
					}
				}
				return criteria.list();
			}
		});

	}
}
